/** @jsxImportSource @emotion/react */
import * as React from "react";
// import { Text } from "./Text";
import PropTypes from "prop-types";
// import { RequestCloseContext } from "./Sheet";
// import { useTheme } from "./Theme/Providers";
// import { noOp } from "./misc/noop";
// import { useTouchable, OnPressFunction } from "./Hooks/touchable-hook";
import cx from "classnames";
// import { safeBind } from "./Hooks/compose-bind";
import {forwardRef, MouseEventHandler, PointerEvent} from "react";
import {useInteractions} from "@floating-ui/react-dom-interactions";

import {
    useTheme,
    VisuallyHidden,
    IconAlertCircle, IconChevronDown,
    Text, LabelText,
    useGestureResponder, StateType, usePrevious, RequestCloseContext,
} from "customize-easy-ui-component";
import {useTouchable, OnPressFunction} from "customize-easy-ui-component/esm/Hooks/touchable-hook";
import {safeBind} from "customize-easy-ui-component/esm/Hooks/compose-bind";
import {noOp} from "customize-easy-ui-component/esm/misc/noop";



const KeyCodes = {
  ArrowUp: 38,
  ArrowDown: 40,
  Home: 36,
  End: 35
};

interface MenuListContextType {
  focus: boolean;
  onKeyDown: (e: React.KeyboardEvent) => void;
}

const MenuListContext = React.createContext<MenuListContextType>({
  focus: false,
  onKeyDown: () => {}
});

type ChildrenType = React.ReactElement<MenuItemProps>;

export interface MenuListProps extends React.HTMLAttributes<HTMLDivElement> {
  /** A combination of MenuItem, MenuLabel, and MenuDivider children */
  children: ChildrenType | ChildrenType[];
  /** Useful if you are providing your own MenuItem children */
  focusableChildren?: React.ComponentType<any>[];
}

export const MenuList: React.FunctionComponent<MenuListProps> = ({
  children,
  focusableChildren = [],
  ...other
}) => {
  const theme = useTheme();
  const disabled = new Map();
  const [focusIndex, setFocusIndex] = React.useState<number | null>(null);
  const kids = React.Children.toArray(children);

  const focusComponents = [MenuItem, ...focusableChildren];
  const focusableItems = kids.filter(
    kid =>
      React.isValidElement(kid) &&
      focusComponents.indexOf(kid.type as React.ComponentType) > -1
  );

  const lastIndex = focusableItems.length - 1;
  const firstIndex = 0;

  return (
    <div
      role="menu"
      onKeyDown={(e: React.KeyboardEvent) => {
          if (
            e.keyCode === KeyCodes.ArrowDown ||
            (e.keyCode === KeyCodes.ArrowUp && focusIndex === null)
          ) {
            e.preventDefault();
            setFocusIndex(0);
          }else if (e.keyCode === 13) {
            //菜单列表 回车 有何意义
            e.stopPropagation();
            e.preventDefault();
          }
      }}
      css={{
        minWidth: "200px",
        display: "block",
        padding: `${theme.spaces.sm} 0`
      }}
      {...other}
    >
      {kids.map(kid => {
        if (!React.isValidElement(kid)) {
          return null;
        }

        const i = focusableItems.indexOf(kid);

        if (i < 0) {
          return kid;
        }

        disabled.set(i, kid.props.disabled);

        function focusDown(current: number) {
          const next = current + 1 > lastIndex ? firstIndex : current + 1;
          if (disabled.get(next)) {
            focusDown(next);
          } else {
            setFocusIndex(next);
          }
        }

        function focusUp(current: number) {
          const next = current - 1 < firstIndex ? lastIndex : current - 1;
          if (disabled.get(next)) {
            focusUp(next);
          } else {
            setFocusIndex(next);
          }
        }

        const index = focusIndex || 0;

        return (
          <MenuListContext.Provider
            key={i}
            value={{
              // !第一个菜单项目 默认就是focus= true;
              focus: i === focusIndex,
              onKeyDown: (e: React.KeyboardEvent) => {
                if (e.keyCode === KeyCodes.ArrowDown) {
                  e.preventDefault();
                  focusDown(index);
                } else if (e.keyCode === KeyCodes.ArrowUp) {
                  e.preventDefault();
                  focusUp(index);
                } else if (e.keyCode === KeyCodes.Home) {
                  e.preventDefault();
                  setFocusIndex(firstIndex);
                } else if (e.keyCode === KeyCodes.End) {
                  e.preventDefault();
                  setFocusIndex(lastIndex);
                }else if (e.keyCode === 13) {
                  //菜单列表 回车 有何意义
                  e.stopPropagation();
                  e.preventDefault();
                }
              }
            }}
          >
            {kid}
          </MenuListContext.Provider>
        );
      })}
    </div>
  );
};

MenuList.propTypes = {
  //focusableChildren: PropTypes.arrayOf(PropTypes.element)
};

//弹出菜单不能noBind；
//MenuItem需要ref()切换，不能被RouterLink代替
//手机ResponsivePopover+MenuItem还会遭遇点击点点透掉的问题；
interface MenuItemProps extends React.HTMLAttributes<Element> {
  /** Called when the menu item is selected. Generally use this instead of onClick. */
  onPress?: OnPressFunction;
  onClick?: (e: React.MouseEvent<HTMLElement>) => void;
  /** Disable this menu item */
  disabled?: boolean;
  /** Pass in a string to use standard text styles. Otherwise, pass in any other node. */
  children: React.ReactNode;
  /** Provide a custom component. Eg., ReactRouter Link */
  component?: React.ElementType<any>;
  /** optional content to appear to the right of the menu text */
  contentAfter?: React.ReactNode;
  /** optional content to appear to the left of the menu text */
  contentBefore?: React.ReactNode;
  /**紧凑布局的*/
  tight?: boolean;
  [key: string]: any;
}
//MenuItem是div+useTouchable绑定；
//类似Button处理。 Can't perform a React state update on an unmounted；手机onPress onClick。估计useTouchable有毛病。
export const MenuItem: React.FunctionComponent<MenuItemProps> = ({
                                                                   contentBefore,
                                                                   contentAfter,
                                                                   onPress = noOp,
                                                                   className = "",
                                                                   component: Component = "div",
                                                                   role = "menuitem",
                                                                   children,
                                                                   disabled,
                                                                   onClick,
                                                                   ...other
                                                                 }) => {
  const theme = useTheme();
  const dark = theme.colors.mode === "dark";
  const localRef = React.useRef<HTMLDivElement>(null);
  //嵌套父辈的Sheet组件提供回调，给菜单被点击了后触发回调,来关闭整个父辈Sheet组件。
  const closeParent = React.useContext(RequestCloseContext);
  const { focus, onKeyDown } = React.useContext(MenuListContext);
  const isLink = Component === "a" || other.href || other.to;
  //touchable-hook底下,触发onScroll（）可能报错 unmount; dispatch<> <- focus-trap()。
  const { bind, hover, active } = useTouchable({
    onPress: select,
    terminateOnScroll: false,
    disabled,
    delay: 0,
    behavior: isLink ? "link" : "button"
  });

  React.useEffect(() => {
    if (focus && localRef.current) {
      //获取输入焦点了, 菜单列表第一个菜单项默认有焦点
      localRef.current.focus();
    }
  }, [focus, localRef]);

  //必须，onPress+ 原生onClick；
  function select() {
    onPress();
    closeParent();
  }
  //const touchScr = useMedia(`(any-pointer: coarse)`);
  //手机和大屏幕的内容维持一致：菜单区域大小高度应该差不多。

  return (
    <Component
      className={cx("MenuItem", "Touchable", className, {
        "Touchable--hover": hover,
        "Touchable--active": active
      })}
      css={[
        {
          cursor: "pointer",
          opacity: disabled ? 0.3 : 1,
          display: "flex",
          textDecoration: "none",
          transition: "background-color 0.1s ease",
          WebkitTapHighlightColor: "transparent",
          color: theme.colors.text.default,
          alignItems: "center",
          ":focus": {
            outline: theme.outline
          },
          ":focus:not([data-focus-visible-added])": {
            outline: "none"
          },
          padding: `${theme.spaces.xs} ${theme.spaces.md}` ,
          [theme.mediaQueries.sm]: {
            padding: `${theme.spaces.none} ${theme.spaces.none}`
          },
          [theme.mediaQueries.md]: {
            padding: `${theme.spaces.xs} calc(${theme.spaces.sm} + 0.25rem)`,
          },
          [theme.mediaQueries.lg]: {
            padding: `${theme.spaces.xs} ${theme.spaces.md}`
          },
          [theme.mediaQueries.xl]: {
            padding: `${theme.spaces.sm} ${theme.spaces.lg}`
          }
        },
        hover && {
          background: dark
            ? theme.colors.background.tint2
            : theme.colors.background.tint1
        },
        active && {
          background: theme.colors.background.tint2
        }
      ]}
      role={role}
      tabIndex={disabled ? -1 : 0}
      data-trigger-close={true}
      {...safeBind(
        bind,
        {
          ref: localRef,
          onKeyDown: (e: React.KeyboardEvent) => {
            //e.stopPropagation();
            e.preventDefault();
            if (onKeyDown) onKeyDown(e);
          },
          onClick: (e: React.MouseEvent) => {
           //e.stopPropagation(); 导致菜单列表父窗口Popover无法被关闭。
          }
        },
        other
      )}
    >
      {contentBefore}
      {typeof children === "string" ? (
        <Text
          wrap={false}
          css={{
            paddingLeft: contentBefore ? theme.spaces.md : 0,
            paddingRight: contentAfter ? theme.spaces.md : 0,
            flex: 1,
            color: "inherit"
          }}
        >
          {children}
        </Text>
      ) : (
        children
      )}
      {typeof contentAfter === "string" ? (
        <Text muted>{contentAfter}</Text>
      ) : (
        contentAfter
      )}
    </Component>
  );
};


MenuItem.propTypes = {
  onSelect: PropTypes.func,
 // component: PropTypes.element,
  disabled: PropTypes.bool,
  children: PropTypes.node,
  contentBefore: PropTypes.node,
  contentAfter: PropTypes.node,
  onPress: PropTypes.func,
  className: PropTypes.string,
  role: PropTypes.string
};

type MenuDividerProps = React.HTMLAttributes<HTMLDivElement>;

export function MenuDivider(props: MenuDividerProps) {
  const theme = useTheme();
  return (
    <div
      css={{
        height: 0,
        margin: `${theme.spaces.sm} 0`,
        overflow: "hidden",
        borderTop: "1px solid",
        borderColor: theme.colors.border.muted
      }}
      {...props}
    />
  );
}

interface MenuLabelProps extends React.HTMLAttributes<HTMLDivElement> {
  /** The name of the label */
  children?: React.ReactNode;
}

export const MenuLabel: React.FunctionComponent<MenuLabelProps> = props => {
  const theme = useTheme();
  return (
    <Text
      variant="uppercase"
      css={{
        padding: `${theme.spaces.xs} ${theme.spaces.md}`
      }}
      {...props}
    />
  );
};

MenuLabel.propTypes = {
  children: PropTypes.node
};

/**将来准备恢复成 MenuItem ？参数不兼容onClick onPress;
 * 非touch事件版,onClick()时间;  DdMenu适用的。
 * 因为从外部注入的方式修正padding 需要像这样的全部都要选择上，或者 但！important！的也太武断
 divStyle={{
        padding: 0,
        [theme.mediaQueries.sm]: {
            padding: 0,
        },
        [theme.mediaQueries.md]: {
            padding: 0,
        },
        [theme.mediaQueries.lg]: {
            padding: 0,
        },
        [theme.mediaQueries.xl]: {
            padding: 0,
        },
    }}
 考虑加一个参数：tight 表示是否紧凑的菜单按钮。
 * */
export const Menu2Item = forwardRef< HTMLButtonElement,
    MenuItemProps
    >(({
              contentBefore,
              contentAfter,
              className = "",
              component: Component = "div",
              onPress = noOp,
              role = "menuitem",
              children,
              disabled,
             // onClick,
              tight,
              ...other
          }, ref) => {

    const theme = useTheme();
    const dark = theme.colors.mode === "dark";

    //const touchScr = useMedia(`(any-pointer: coarse)`);
    //手机和大屏幕的内容维持一致：菜单区域大小高度应该差不多。
    return (
        <Component
            className={cx("MenuItem", "Touchable", className )}
            css={[
                {
                    cursor: "pointer",
                    opacity: disabled ? 0.3 : 1,
                    display: "flex",
                    lineHeight: theme.lineHeights.menus,
                    textDecoration: "none",
                    transition: "background-color 0.1s ease",
                    WebkitTapHighlightColor: "transparent",
                    color: theme.colors.text.default,
                    alignItems: "center",
                    ":focus": {
                        outline: theme.outline
                    },
                    ":focus:not([data-focus-visible-added])": {
                        outline: "none"
                    },
                    ":hover": {
                        background:  theme.colors.background.tint1
                    },
                    padding: 0,
                },
                !tight && (
                    {
                        padding: `${theme.spaces.xs} ${theme.spaces.sm}` ,
                        [theme.mediaQueries.sm]: {
                            padding: `${theme.spaces.none} ${theme.spaces.none}`
                        },
                        [theme.mediaQueries.md]: {
                            padding: `${theme.spaces.xs} calc(${theme.spaces.xs} + 0.35rem)`,
                        },
                        [theme.mediaQueries.lg]: {
                            padding: `${theme.spaces.xs} ${theme.spaces.md}`
                        },
                        [theme.mediaQueries.xl]: {
                            padding: `${theme.spaces.sm} ${theme.spaces.lg}`
                        },
                    }
                ),
            ]}
            role={role}
            tabIndex={disabled ? -1 : 0}
            data-trigger-close={true}
            {...safeBind(
                {
                    ref: ref,
                    onClick: (e: React.MouseEvent) => {
                        console.log("弹出3菜Menu2ImmT !点了");
                        !disabled && onPress(e);
                    },
                    // onPointerUp: (e: React.PointerEvent ) => {  基本点击触发
                    //  加上能使得DdMenu在位于Panable可随意拉拽的组件底下，能够触发"lostpointercapture"的useDrag(state)消息event.type
                    //     e.stopPropagation();  }
                },
                other
            )}
        >
            {contentBefore}
            {typeof children === "string" ? (
                <Text
                    wrap={true}
                    css={{
                        paddingLeft: contentBefore ? theme.spaces.sm : 0,
                        paddingRight: contentAfter ? theme.spaces.sm : 0,
                        flex: 1,
                        color: "inherit",
                        lineHeight: theme.lineHeights.menus,
                    }}
                >
                    {children}
                </Text>
            ) : (
                children
            )}
            {typeof contentAfter === "string" ? (
                <Text muted>{contentAfter}</Text>
            ) : (
                contentAfter
            )}
        </Component>
    );
});
